﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>linq.js tutorial</title>
    <script type="text/javascript" src="../linq.js"></script>
    <script type="text/javascript">
        var textStack = []
        document.write = function ()
        {
            for (var i = 0; i < arguments.length; i++)
            {
                textStack.push(arguments[i]);
            }
        }

        window.onload = function ()
        {
            Enumerable.From(document.getElementsByTagName("pre"))
                .ForEach(function (ele)
                {
                    eval(ele.innerText || ele.textContent);
                    var p = document.createElement("p");
                    p.innerHTML = textStack.join("");
                    ele.appendChild(p);
                    textStack.length = 0;
                });
        }
    </script>
</head>
<body>
    <h2>
        First step of Lambda Expression</h2>
    <pre>
    // Anonymous function
    Enumerable.Range(1, 3).Select(function(value, index) { return index + ':' + value }).WriteLine();
    // String like Lambda Expression (arguments => expression)
    Enumerable.Range(1, 3).Select("value,index=>index+':'+value").WriteLine();
    
    // If the number of arguments is one , can use default iterator variable '$'
    Enumerable.Range(1, 3).Select("i=>i*2").WriteLine();
    Enumerable.Range(1, 3).Select("$*2").WriteLine(); // same
    
    // "" is shortcut of "x => x" (identity function)
    Enumerable.Range(4, 7).Join(Enumerable.Range(8, 5), "", "", "outer,inner=>outer*inner").WriteLine();
    </pre>
    <h2>
        Scope of lambda expression</h2>
    <pre>
    var number = 3;
    // Can't Find number | lambda expression can use only global variable
    // Enumerable.Range(1,10).Where("$ == number").WriteLine();

    // use anonymous founction, can capture variable
    Enumerable.Range(1,10).Where(function(i){return i == number}).WriteLine();
    </pre>
    <h2>
        From(Object) -> convert to KeyValuePair</h2>
    <pre>
    var object = {foo:"a", "bar":100, "foobar":true};
    Enumerable.From(object).ForEach(function(obj)
    {
        document.write(obj.Key + ":" + obj.Value + "&lt;br />");
    })
    </pre>
    <h2>
        ForEach (continue and break)</h2>
    <pre>
    Enumerable.Repeat("foo", 10).ForEach(function(value, index)
    {
        if (index % 2 == 0) return; // continue
        if (index > 6) return false; // break
        document.write(index + ":" + value + "&lt;br />");
    });
    </pre>
    <h2>
        Grouping and ref/value compare</h2>
    <pre>
    // ref compare
    document.write((new Date(2000, 1, 1) == new Date(2000, 1, 1)) + "&lt;br />"); // false
    document.write(({ a: 0} == { a: 0 }) + "&lt;br />"); // false
    
    document.write("------" + "&lt;br />");
    var objects = [
        { Date: new Date(2000, 1, 1), Id: 1 },
        { Date: new Date(2010, 5, 5), Id: 2 },
        { Date: new Date(2000, 1, 1), Id: 3 }
    ]

    // ref compare, can not grouping
    Enumerable.From(objects)
        .GroupBy("$.Date", "$.Id",
            function (key, group) { return { date: key, ids: group.ToString(',')} })
        .WriteLine("$.date + ':' + $.ids");

    document.write("------" + "&lt;br />");

    // use fourth argument(compareSelector)
    Enumerable.From(objects)
        .GroupBy("$.Date", "$.Id",
            function (key, group) { return { date: key, ids: group.ToString(',')} },
            function (key) { return key.toString() })
        .WriteLine("$.date + ':' + $.ids");
        </pre>
    <h2>
        Regular Expression Matches</h2>
    <pre>
    // Enumerable.Matches return Enumerable&lt;MatchObject>

    var input = "abcdefgABzDefabgdg";
    Enumerable.Matches(input, "ab(.)d", "i").ForEach(function(match)
    {
        for (var prop in match)
        {
            document.write(prop + " : " + match[prop] + "&lt;br />");
        }
        document.write("toString() : " + match.toString() + "&lt;br />");
        document.write("---" + "&lt;br />");
    });
    </pre>
    <h2>
        LazyEvaluation and InfinityList</h2>
    <pre>
    // first radius of circle's area over 10000
    var result = Enumerable.ToInfinity(1).Where("r=>r*r*Math.PI>10000").First();
    document.write(result);
    </pre>
    <h2>
        Dictionary</h2>
    <pre>
    // sample class
    var cls = function (a, b)
    {
        this.a = a;
        this.b = b;
    }
    var instanceA = new cls("a", 100);
    var instanceB = new cls("b", 2000);

    // create blank dictionary
    var dict = Enumerable.Empty().ToDictionary();
    // create blank dictionary(use compareSelector)
    var dict = Enumerable.Empty().ToDictionary("","",function (x) { return x.a + x.b });

    dict.Add(instanceA, "zzz");
    dict.Add(instanceB, "huga");
    document.write(dict.Get(instanceA) + "&lt;br />"); // zzz
    document.write(dict.Get(instanceB) + "&lt;br />"); // huga

    // enumerable (to KeyValuePair)
    dict.ToEnumerable().ForEach(function (kvp)
    {
        document.write(kvp.Key.a + ":" + kvp.Value + "&lt;br />");
    });
    </pre>
    <h2>
        sample - Nondeterministic Programs</h2>
    // from Structure and Interpretation of Computer Programs 4.3.2
    <pre>
    var apart = Enumerable.Range(1, 5);
    var answers = apart
        .SelectMany(function(baker){ return apart
        .SelectMany(function(cooper){ return apart
        .SelectMany(function(fletcher){ return apart
        .SelectMany(function(miller){ return apart
        .Select(function(smith){ return {
            baker: baker, cooper: cooper, fletcher: fletcher, miller: miller, smith: smith}})})})})})
        .Where("Enumerable.From($).Distinct('$.Value').Count() == 5")
        .Where("$.baker != 5")
        .Where("$.cooper != 1")
        .Where("$.fletcher != 1 && $.fletcher != 5")
        .Where("$.miller > $.cooper")
        .Where("Math.abs($.smith - $.fletcher) != 1")
        .Where("Math.abs($.fletcher - $.cooper) != 1");

    answers.SelectMany("").WriteLine("$.Key + ':' + $.Value");
    </pre>
</body>
</html>
